/*
 * Network.h
 *
 *   Created on: 2010-1-17     
 *  Description: socket相关操作集合类（可跨平台）
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#ifndef NETWORK_H_
#define NETWORK_H_

#include <string>

#include "EasyAddr.h"

//主要的网络操作类
class Network
{
public:

	/* 创建一个ipv4的socket
	 * @param type TCP(默认)还是UDP，见enum TRANS_TYPE
	 * @return 如果成功>0;失败返回-1
	 */
	static int socket(unsigned short type = TCP);

	/* 关闭一个socket的fd
	 * @param fd 被关闭的fd
	 * @return 如果成功true;失败false
	 */
	static bool close(int fd);

	/* 绑定端口
	 * @param fd 要绑定的fd
	 * @param addr 要绑定到哪个地址(暂只支持ipv4)
	 * @param port 要绑定到哪个端口
	 */
	static bool bind(int fd, unsigned int port, const std::string& ip = "");

	/* 打开被动监听
	 * @param fd socket的fd
	 * @param backlog 队列最大长度
	 * @return 是否listen成功
	 */
	static bool listen(int fd, int backlog = 20);

	/* 接受client的连接
	 * @param fd server的fd
	 * @param addr client的addr信息
	 */
	static int accept(int serverFd, struct sockaddr_in* addr);

	/* 接受client的连接
	 * @param fd server的fd
	 * @param addr client的addr信息
	 */
	static int accept(int serverFd, EasyAddr& addr);

	/* 连接到Server
	 * @param sock socket的fd
	 * @param addr server的地址和port信息
	 * @return 如果本次读取成功(读取了0)true，错误false
	 */
	static bool connect(int sock, struct sockaddr_in *addr);

	/* 连接到Server
	 * @param sock socket的fd
	 * @param addr server的地址和port信息
	 * @return 如果本次读取成功(读取了0)true，错误false
	 */
	static bool connect(int sock, const EasyAddr &addr);

	/* 非阻塞地读取socket上的数据
	 * @param fd socket的fd
	 * @param buf 用于存放字节的缓冲区
	 * @param eof 是否到了末端
	 * @param len 每次最多接收多少字节
	 * @return 如果本次读取成功(读取了0)true，发生严重错误false
	 */
	static bool recvBytes(int fd, std::string &buf, bool &eof,
			unsigned long len = 1024);

	/* 非阻塞的socket发送数据
	 * @param fd socket的fd
	 * @param buf 待发送数据的缓冲区
	 * @param nLeft 还剩下多少字节没有发送
	 * @return 是否发送成功
	 */
	static bool sendBytes(int fd, const std::string &buf, unsigned long& nLeft);

	/* 设置一个fd为非阻塞模式
	 * @param fd 被设置的fd
	 * @return 如果成功true;失败false
	 */
	static bool setNonBlocking(int fd);

	/* 设置fd的超时,请在connect之前使用
	 * @param 被设置的fd
	 */
	static bool setTimeOut(int fd, unsigned int timeout);

	/* 把sockaddr_in这类地址转换成容易阅读的格式
	 * @param addr 要转换的地址格式
	 * @return 容易阅读的地址格式ip:port
	 */
	static EasyAddr easyAddr(const struct sockaddr_in& addr);

	/* 把ip:port这类地址转换成内部格式的地址
	 * @param host ip地址
	 * @param port 端口
	 * @param addr 地址
	 * @return 容易阅读的地址格式ip:port
	 */
	static bool sockAddr(const std::string &ip, unsigned int port,
			sockaddr_in *addr);
	/* 把ip:port这类地址转换成内部格式的地址
	 * @param addStr 容易读取的ip:port格式
	 * @param addr 地址
	 * @return 容易阅读的地址格式ip:port
	 */
	static bool sockAddr(const EasyAddr &easy, sockaddr_in *addr);

	//传输层协议类型
	enum TRANS_TYPE
	{
		TCP = 1, UDP = 2
	};

private:
	//单件类
	Network();
	virtual ~Network();

	/* 判断是否是致命错误
	 * @param err 要判断的errno
	 * @return 如果是非阻塞引起的无数据可以读返回false，否则返回true
	 */
	static bool isFatalError(int err);
};

#endif /* NETWORK_H_ */
